﻿#include <iostream>
#include <memory.h>
#include <deque>
#include <stdio.h>

using  namespace std;

/*
https://www.acwing.com/problem/content/6/


有 N种物品和一个容量是 V的背包。
第 i种物品最多有 si件，每件体积是 vi，价值是 wi。

求解将哪些物品装入背包，可使物品体积总和不超过背包容量，且价值总和最大。
输出最大价值。

输入格式
第一行两个整数，N，V (0<N≤1000, 0<V≤20000)
，用空格隔开，分别表示物品种数和背包容积。

接下来有 N行，每行三个整数 vi,wi,si
，用空格隔开，分别表示第 i种物品的体积、价值和数量。

输出格式
输出一个整数，表示最大价值。

数据范围
0<N≤1000

0<V≤20000

0<vi,wi,si≤20000
提示
本题考查多重背包的单调队列优化方法。

输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例：
10
*/

const int N = 20010;
int g[N], f[N];
int q[N];
int n, m;

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        int v, w, s;
        cin >> v >> w >> s;
        //f[]是当前dp  g[]是上一次dp ,体积是索引
        memcpy(g, f, sizeof f);
        for (int j = 0; j < v; j++) {
            int hh = 0; int tt = -1;
            for (int k = j; k <= m; k += v) {
                //本次的体积k 取s个物品 那么 最多需要f[k-s*v]的数据 比k-s*v小的体积 弹出队列
                while (hh <= tt && k - s * v > q[hh]) hh++;
                //得到f[k]的最大值
                if (hh <= tt) f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w);
                //排除无需在比较的体积v  为啥减去额外的w？
                //自己做了修改 q[tt]和k在相同情况下比较决定是否弹出。 补上了两者v相差的额外w
                while (hh <= tt && g[q[tt]] + (k - q[tt]) / v * w < g[k]) tt--;
                q[++tt] = k;
            }
        }
    }

    cout << f[m] << endl;

    return 0;
}